<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Goutte\Client;
use GuzzleHttp\Client as GuzzleClient;

use App\Models\Issue;
use App\Models\ArticleCat;
use App\Models\Article;
use App\Models\Author;
use App\Models\Affiliation;

use DB;

class FetchArticles extends Command
{
    const ISSUE_URL_PREFIX = 'http://www.zoores.ac.cn/EN/volumn/volumn_%u.shtml';
    const ARTICLE_URL_PREFIX = 'http://www.zoores.ac.cn/EN/abstract/abstract%u.shtml';

    const JOURNAL_ID = 1;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fetch:article {id?} {--I|issue=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    private $client;
    private $volume_id = 0;
    private $issue_id = 0;
    private $count = 0;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {

        $client = new Client();
        $guzzleClient = new GuzzleClient(array(
            'timeout' => 60,
        ));
        $client->setClient($guzzleClient);
        $this->client = $client;
        $id = $this->argument('id');
        $issueId = $this->option('issue');
        if ($id) {
            $this->getArticleById($id);
        }

        if ($issueId) {
            $this->getArticleLinkByIssue($issueId);
        }

        if (!$id && !$issueId) {

            $page = 1;

            $count = 0;
            while (true) {
                $issues = Issue::simplePaginate(5, ['*'], 'page', $page);
                $break = (bool)(count($issues->items()) == 0);

                foreach ($issues->items() as $item) {
                    if ($item->zr_id == 0) continue;

                    $this->issue_id  = $item->issue;
                    $this->volume_id  = $item->volume;
                    $this->getArticleLinkByIssue($item->zr_id);
                    $count++;

                    // if ($count%5 == 0)  sleep(2);

                    $this->info($count . 'th issue fetched');
                }

                if($break) break;

                $page++;
            }

            $this->info('Done for all articles, ' . $count . 'issues fetched');
        }

    }

    public function getArticleLinkByIssue($issueId)
    {
        $issueUrl = sprintf(self::ISSUE_URL_PREFIX, $issueId); //self::ISSUE_URL_PREFIX . $issueId . '.shtml';
        // $issueUrl = 'http://www.zoores.ac.cn/EN/2095-8137/current.shtml';
        
        try {
            $cawler = $this->client->request('GET', $issueUrl);
            $items = $cawler->filterXpath('//a[@class="txt_biaoti"]');
            $this->info('Fetching issue, issue ID: ' . $issueId);

            $items->each(function($item, $i) {
                $link = $item->link()->getUri();
                if (preg_match('/abstract(\d+)\.shtml/', $link, $matches)) {
                    $aId = $matches[1];
                    $this->getArticleById($aId);
                    $this->count++;

                    $this->info($this->count . 'th article fetched.');
                }
            });

            $this->info('Fetched Issue done, ID: ' . $issueId);
        } catch(\Exception $e) {
            print_r($e->getMessage());exit;
        }
    }

    public function getArticleById($id)
    {
        if (Article::where('zr_id', $id)->first() || in_array($id, [2769, 2780])) {
            return null;
        }

        $articleUrl = sprintf(self::ARTICLE_URL_PREFIX, $id);

        try {
            $this->info('Fetching article, article ID: ' . $id);
            $crawler = $this->client->request('GET', $articleUrl);
            $issueItem = $crawler->filterXpath('//span[@class="style1"]')->eq(0)->parents();
            $nbsp = html_entity_decode("&nbsp;");
            $issueItemText = str_replace($nbsp, '', html_entity_decode($issueItem->text()));
            // ?Vol\.\s+(\d+).*?Issue\s+\((\d+)\).*?DOI:\s+([\d+\.\/\w-_]+)\s+
            $doi = '';

            // 3121 - 3138  wrong
            if (preg_match('/(\d{4}).*?Vol\.\s+(\d+)?.*?Issue\s+\((\S+)\).*?(\d+)?-(\d+)?.*?DOI:\s+([\d+\.\/\w-_]+)?\s+/is', $issueItemText, $matches)) {
                $year = $matches[1];
                $volume = $matches[2];
                $issue = $matches[3];
                $pageStart = $matches[4];
                $pageEnd = isset($matches[5]) ? $matches[5] : null;
                $doi = isset($matches[6]) ? $matches[6] : '';

                if ($issue && !$volume) {
                    $volume = $this->volume_id;
                }
                $issueObj = Issue::on()
                    ->where('year', $year)
                    ->where('volume', $volume)
                    ->where('issue', $issue)
                    ->first();

                if ($year && $volume && $issue && !$issueObj) {
                    $issueObj = new Issue;
                    $issueObj->title = $year . ' Vol.' . $volume . ' No.' . $issue;
                    $issueObj->year = $year;
                    $issueObj->volume = $volume;
                    $issueObj->issue = $issue;
                    $issueObj->page_start = $pageStart ?: 0;
                    $issueObj->page_end = $pageEnd ?: 0;
                    $issueObj->journal_created = date('Y-m-d');
                    $issueObj->journal_published = date('Y-m-d');
                    $issueObj->zr_id = 0;

                    $issueObj->save();

                }
                $cate = trim($crawler->filterXpath('//span[@class="J_lanmu"]')->text());
                $cateObj = ArticleCat::on()->where('name', $cate)->first();

                $title = $crawler->filterXpath('//div[@class="J_biaoti_en"]')->html();
                $authorsItem = $crawler->filterXpath('//td[@class="J_author_EN"]');
                $authorList = '';
                if ($authorsItem->count() > 0) {
                    $authorList = $authorsItem->html();
                }
                // if ($authorsItem->count() > 0) {
                //     if (strpos($authorsItem->text(), ';')) {
                //         $authorsArr = preg_split('/;\s?/', $authorsItem->text()); //explode('; ', $authorsItem->text());
                //     } else {
                //         $authorsArr = preg_split('/,\s?/', $authorsItem->text()); //explode(', ', $authorsItem->text());
                //     }
                //     $authors = [];
                //     foreach ($authorsArr as $author) {
                //         $tArr = [];
                //         $aff = '';
                //         // print_r($author);exit;
                //         if (preg_match('/(\d+.*)?$/', $author, $matches)) {
                //             $aff = isset($matches[1]) ? $matches[1] : null;
                //         }

                //         $tArr['affiliation'] = $aff;
                //         $tArr['correspondence'] = (int)strpos($aff, '*');

                //         $name = substr($author, 0, -strlen($aff));

                //         if ($p = strrpos($name, ' ')) {
                //             $tArr['firstname'] = substr($name, 0, $p);
                //             $tArr['lastname'] = substr($name, $p + 1);
                //         } else {
                //             $tArr['firstname'] = '';
                //             $tArr['lastname'] = $name;
                //         }

                //         $authors[] = $tArr;
                //     }
                // }


                $affItems = $crawler->filterXpath('//td[@class="J_author"]');
                $affiliation = '';
                if ($affItems->count() > 0) {
                    $affiliation = $affItems->html();
                }
                // if ($affItems->count() > 0) {
                //     $affInfo = $affItems->html();
                //     $affArr = array_map(function($v) use ($id) {
                //         $item = trim($v);
                //         $nb = mb_substr($item, 0, 1);
                //         $info = mb_substr($item, 2);

                //         if (in_array($id, [0])) {
                //             return [
                //                 'nb' => '',
                //                 // 'info' => 'НАЧАЛЬНОЕ ИССЛЕДОВАНИЕ ПИТАНИЯ Ithaginis cruentus ВЛАНЬПИН-ЪЕХОСКОМ ЗАПОВЕТНИКЕ Sichuan'
                //                 'info' => ''
                //             ];
                //         }

                //         $info = iconv(mb_detect_encoding($info), 'utf-8//IGNORE', $info);
                //         return [
                //             'nb' => $nb,
                //             'info' => trim((string)$info)
                //         ];
                //     }, explode('<br>', $affInfo));
                // }

                if ($crawler->filterXpath('//form[@id="refForm"]')->count() > 0) {
                    $abstractItem = $crawler->filterXpath('//form[@id="refForm"]')->previousAll()->first();
                    if ($abstractItem->count() > 0) {
                        $abstract = trim(str_replace([$nbsp, 'Abstract'], ['', ''], html_entity_decode($abstractItem->text())));
                    }

                    $keywordsItems = $crawler->filterXpath('//span[@class="J_zhaiyao"]//a[@class="txt_zhaiyao1"]');

                    if ($keywordsItems->count() > 0) {
                        $keywords = [];
                        $keywordsItems->each(function($item, $i) use (&$keywords) {
                            $keywords[] = $item->text();
                        });
                    }

                    $infoItem = $crawler->filterXpath('//form[@id="refForm"]')->nextAll();
                    if ($infoItem->count() > 2) {
                        $fundItem = $infoItem->eq(2);
                        $fund = trim(mb_substr($fundItem->text(), 5));
                    }
                    if ($infoItem->count() > 3) {
                        $corresInfo = $infoItem->eq(3)->text();

                        $corresInfo = trim(str_replace('Corresponding Authors:', '', $corresInfo));
                        // print_r($corresInfo);exit;
                    }
                }

                $iArr = [
                    'journal_id' => self::JOURNAL_ID,
                    'issue_id' => (isset($issueObj) && $issueObj) ? $issueObj->id : $this->issue_id,
                    'page_start' => isset($pageStart) ? (int)$pageStart : 0,
                    'page_end' => isset($pageEnd) ? (int)$pageEnd : 0,
                    'cite_count' => 0,
                    'cate_id' => (isset($cateObj) && $cateObj) ? $cateObj->id : 0,
                    'title' => $title,
                    'id_doi' => $doi,
                    'abstract' => isset($abstract) ? $abstract : '',
                    'keywords' => isset($keywords) ? implode('; ', $keywords) : '',
                    'accept_date' => date('Y-m-d H:i:s'),
                    'revision_date' => date('Y-m-d H:i:s'),
                    'publish_date' => date('Y-m-d H:i:s'),
                    'fund' => isset($fund) ? $fund : '',
                    'author_list' => $authorList,
                    'affiliation' => $affiliation,
                    'corresponding_info' => isset($corresInfo) ? $corresInfo : ''
                ];

                Article::updateOrCreate(['zr_id' => $id], $iArr);

                // $article = Article::on()->where('zr_id', $id)->first();

                // if ($article) {
                //     Author::where('article_id', $article->id)->delete();

                //     if (isset($authors)) {
                //         foreach ($authors as $author) {
                //             Author::create([
                //                 'article_id' => $article->id,
                //                 'firstname' => $author['firstname'],
                //                 'lastname' => $author['lastname'],
                //                 'email' => isset($author['email']) ?? null,
                //                 'affiliation' => $author['affiliation'],
                //                 'correspondence' => $author['correspondence']
                //             ]);
                //         }
                //     }


                //     Affiliation::where('article_id', $article->id)->delete();

                //     if (isset($affArr)) {
                //         foreach ($affArr as $aff) {
                //             Affiliation::create([
                //                 'article_id' => $article->id,
                //                 'number' => $aff['nb'],
                //                 'name' => $aff['info']
                //             ]);
                //         }
                //     }
                // }

                // sleep(1);  // sleep
                $this->info('Fetching article done, article ID: ' . $id);
            } else {
                $this->error('One article failed, id: ' . $id);
            }
            // print_r($issueItem->text());exit;
        } catch (\Exception $e) {
            print_r($e->getMessage());exit;
        }
    }
}
